<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:c="livcos.org/ns/cosmos"
  xmlns:u="livcos.org/ns/cosmos/update"
  xmlns:t="livcos.org/ns/cosmos/type"
  xmlns:job="livcos.org/ns/process/job"
  xmlns="livcos.org/ns/doc"
  xmlns:doc="livcos.org/ns/doc"
  xmlns:f="livcos.org/ns/xslt/function"
  exclude-result-prefixes="c t doc f">

  <xsl:import href="EditContent.xsl" />
  <xsl:import href="style/SimpleId.xsl" />
  
  <xsl:param name="objId"/>
  <xsl:param name="scope"/>
  <xsl:param name="id"/>
  <xsl:param name="path" select="'.'" />
  <xsl:param name="view"/>
	
	<xsl:variable name="integrityCheckObjId" select="'/livcos.org/web/editor/integrity'"/>

  <xsl:variable name="idPath">
    <xsl:choose>
      <xsl:when test="(normalize-space($id) = '') or ($id = $objId)">
        <!-- take the root entity -->
        <xsl:text>.</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="idPath">
          <xsl:with-param name="id" select="normalize-space($id)" />
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:template match="/">
    <u:context ref="{$objId}" scope="{$scope}">
      <u:context select="{$idPath}">
        <xsl:apply-templates select="$jobObject/c:request/parameter/*" />
      </u:context>
    </u:context>
    <job:transform def="{$integrityCheckObjId}">
      <job:param name="obj" value="{$objId}"/>
    </job:transform>
  	<job:feed ref="/livcos.org/web/editor/EditResponse" stream="response" base="job">
  		<job:param name="view" value="{$view}"/>
  	</job:feed>
  </xsl:template>
  
	<xsl:template match="*">
	</xsl:template>
	
	<xsl:template match="insertElement">
    <u:insert select="{$path}" create-path="yes">
      <xsl:apply-templates select="../*[starts-with(name(.),'ns')]" mode="ns"/>
      <xsl:element name="{../content}" />
    </u:insert>
  </xsl:template>
  
  <xsl:template match="insertAttribute">
    <u:insert select="{$path}" create-path="yes">
      <xsl:apply-templates select="../*[starts-with(name(.),'ns')]" mode="ns"/>
      <u:attribute name="{../content}">-- value --</u:attribute>
    </u:insert>
  </xsl:template>
  
  <xsl:template match="insert">
    <u:insert select="{$path}" create-path="yes">
    	<xsl:if test="../into = '0'">
    		<xsl:attribute name="position">before</xsl:attribute>
    	</xsl:if>
      <xsl:apply-templates select="../*[starts-with(name(.),'ns')]" mode="ns"/>
    	<xsl:call-template name="buildContent">
    		<xsl:with-param name="content" select="../content/node()"/>
    	</xsl:call-template>
    </u:insert>
  </xsl:template>
  
	<xsl:template match="insert[../tmplObjId]">
		<xsl:call-template name="insert-tmpl"/>
	</xsl:template>
	
	<xsl:template match="insert[../path = '@xmlns']" priority="1">
    <u:decl-namespace select="." prefix="prefix" uri="uri.namespace"/>
  </xsl:template>
	
	<xsl:template name="insert-tmpl">
		<u:info>
			<template ref="{../tmplObjId}#{../tmplId}"/>
		</u:info>
		<u:insert select="{$path}" create-path="yes">
			<xsl:if test="../into = '0'">
				<xsl:attribute name="position">before</xsl:attribute>
			</xsl:if>
			<xsl:apply-templates select="../*[starts-with(name(.),'ns')]" mode="ns"/>
			<xsl:variable name="tmplId" select="../tmplId"/>
			<xsl:variable name="url">
				<xsl:value-of select="../tmplObjId"/>
				<xsl:text>.view?arg1=</xsl:text>
				<xsl:value-of select="encode-for-uri(../tmplArg1)"/>
				<xsl:text>&amp;arg2=</xsl:text>
				<xsl:value-of select="encode-for-uri(../tmplArg2)"/>
				<xsl:text>&amp;arg3=</xsl:text>
				<xsl:value-of select="encode-for-uri(../tmplArg3)"/>
				<xsl:text>&amp;arg4=</xsl:text>
				<xsl:value-of select="encode-for-uri(../tmplArg4)"/>
				<xsl:text>&amp;arg5=</xsl:text>
				<xsl:value-of select="encode-for-uri(../tmplArg5)"/>
			</xsl:variable>
			<xsl:apply-templates select="doc($url)/*//*[@id = $tmplId]/t:content/node()" mode="tmpl"/>
		</u:insert>
		<xsl:if test="../content | ../group/content">
			<u:context select="{$path}/node()[last()]">
				<xsl:call-template name="update"/>
			</u:context>
		</xsl:if>
	</xsl:template>
	
	<xsl:template match="update">
		<xsl:call-template name="update"/>
	</xsl:template>
	
	<xsl:template match="update[../tmplObjId]">
		<xsl:call-template name="insert-tmpl"/>
	</xsl:template>
	
	<xsl:template name="update">
		<xsl:for-each select="../group[path and not(starts-with(path, 'name('))]">
    	<xsl:call-template name="doUpdate">
        <xsl:with-param name="path" select="path"/>
        <xsl:with-param name="content" select="content/node()"/>
        <xsl:with-param name="type" select="type"/>
      </xsl:call-template>
    </xsl:for-each>
    <xsl:for-each select="../group[starts-with(path, 'name(')]">
    	<xsl:call-template name="doUpdate">
        <xsl:with-param name="path" select="path"/>
        <xsl:with-param name="content" select="content/node()"/>
        <xsl:with-param name="type" select="type"/>
      </xsl:call-template>
    </xsl:for-each>
    <xsl:if test="not(../group[path])">
    	<xsl:call-template name="doUpdate">
        <xsl:with-param name="path" select="$path"/>
        <xsl:with-param name="content" select="../content/node()"/>
        <xsl:with-param name="type" select="../type"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
  
	<xsl:template name="doUpdate">
		<xsl:param name="path"/>
		<xsl:param name="content"/>
		<xsl:param name="type"/>
		<xsl:variable name="_content">
			<xsl:call-template name="buildContent">
				<xsl:with-param name="content" select="$content"/>
				<xsl:with-param name="type" select="$type"/>
			</xsl:call-template>
		</xsl:variable>
		<xsl:choose>
			<xsl:when test="contains($path, '@') and (string($_content) = '')">
				<u:delete select="{$path}" />
			</xsl:when>
			<xsl:otherwise>
				<u:update select="{$path}" create-path="yes">
					<xsl:apply-templates select="../*[starts-with(name(.),'ns')]" mode="ns"/>
					<xsl:copy-of select="$_content"/>
				</u:update>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template match="update[contains(../id, '@xmlns:')]">
		<u:decl-namespace select="." prefix="{substring-after(../id,'@xmlns:')}" uri=""/>
    <u:decl-namespace select="." prefix="{../group[path = '@prefix']/content}" uri="{../group[path = '.']/content}"/>
  </xsl:template>
  
  <xsl:template match="delete">
    <u:delete select="." />
  </xsl:template>
  
  <xsl:template match="delete[contains(../id, '@xmlns')]">
    <u:decl-namespace select="." prefix="{substring-after(../id,'@xmlns:')}" uri=""/>
  </xsl:template>
  
  <xsl:template match="clone">
    <u:info>
      <copy object="{$objId}">
        <xsl:choose>
          <xsl:when test="matches($id, '^[0-9]')">
            <xsl:attribute name="node"><xsl:value-of select="$id"/></xsl:attribute>
          </xsl:when>
          <xsl:otherwise>
            <xsl:attribute name="entity"><xsl:value-of select="$id"/></xsl:attribute>
          </xsl:otherwise>
        </xsl:choose>
      </copy>
    </u:info>
    <u:insert position="after" select=".">
      <xsl:choose>
        <xsl:when test="$livcos_version >= '0.3'">
          <u:copy-of select="."/>
        </xsl:when>
        <xsl:otherwise>
          <u:copy-of select="preceding-sibling::*[1]"/>
        </xsl:otherwise>
      </xsl:choose>
    </u:insert>
  </xsl:template>
  
	<xsl:template match="addRelated">
		<xsl:variable name="e" select="doc($objId)/*//*[@id = $id]"/>
		<xsl:variable name="tmplUri"
		select="concat('/livcos.org/type/template/', namespace-uri($e), '/', local-name($e))"/>
		<xsl:variable name="r" select="f:entity($e/@ref, $e)"/>
		<xsl:variable name="relsViewUri"
			select="concat('/livcos.org/type/related/', namespace-uri($r), '/', local-name($r))"/>
		<xsl:variable name="related"
			select="doc(concat($relsViewUri, '?ref=', f:object-id($r), '&amp;id=', $r/@id))/*/*"/>
		<u:insert position="after" select=".">
			<xsl:for-each-group select="$related" group-by="@ref">
				<xsl:if test="not($e/../*[f:resolve-object-id(@ref, .) = current()/@ref])">
					<xsl:variable name="tmpl"
						select="doc(concat($tmplUri, '?ref=', replace(f:relativize-uri(@ref, $objId), '#', '&amp;id=')))/*"/>
					<xsl:copy-of select="$tmpl/*[1]/t:content/node()"/>
				</xsl:if>
			</xsl:for-each-group>
		</u:insert>
	</xsl:template>
	
	<xsl:template match="create">
		<xsl:variable name="e" select="document(concat($objId, '.content'))/*//*[@id = $id]"/>
		<u:insert position="after" select=".">
			<u:copy-of ref="/livcos.org/type/template/{namespace-uri($e)}/{local-name($e)}"
				select="*[1]/t:content/node()">
				<u:namespace prefix="t" uri="livcos.org/ns/cosmos/type"/>
			</u:copy-of>
		</u:insert>
	</xsl:template>
	
	<xsl:template match="rename">
    <xsl:for-each select="../group[path]">
      <u:rename select="{path}" name="{content}"/>
    </xsl:for-each>
    <xsl:if test="not(../group[path])">
      <u:rename select="{$path}" name="{../content}"/>
    </xsl:if>
  </xsl:template>
  
  <xsl:template match="*" mode="ns">
    <u:namespace prefix="{substring(name(),4)}" uri="{.}"/>
  </xsl:template>
  
  <xsl:template match="ns" mode="ns">
    <u:namespace uri="{.}"/>
  </xsl:template>
  
  <xsl:template match="node()" mode="tmpl">
    <xsl:copy-of select="."/>
  </xsl:template>
  
  <xsl:template match="t:attribute" mode="tmpl">
    <u:attribute name="{@name}"><xsl:value-of select="."/></u:attribute>
  </xsl:template>
  
</xsl:stylesheet>
